﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using aaaSoft.SkinEngine.SkinHelpers;
using System.Diagnostics;

namespace aaaSoft.SkinEngine.MyControls
{
    class MyListView:IMyControl
    {
        ListView lvBase;
        SkinEngine skinEng;

        public ListViewItem highLighItem = null;

        public MyListView(ListView lv, SkinEngine skinEng)
        {
            lvBase = lv;
            this.skinEng = skinEng;

            lvBase.FullRowSelect = true;
        }

        public void StopControlSkin()
        {
            lvBase.OwnerDraw = false;
            lvBase.DrawColumnHeader -= new DrawListViewColumnHeaderEventHandler(lvBase_DrawColumnHeader);
            lvBase.DrawItem -= new DrawListViewItemEventHandler(lvBase_DrawItem);
            lvBase.MouseMove -= new MouseEventHandler(lvBase_MouseMove);
            lvBase.MouseLeave -= new EventHandler(lvBase_MouseLeave);
            lvBase.SizeChanged -= new EventHandler(lvBase_SizeChanged);
        }

        public void StartControlSkin()
        {
            lvBase.OwnerDraw = true;
            lvBase.DrawColumnHeader += new DrawListViewColumnHeaderEventHandler(lvBase_DrawColumnHeader);
            lvBase.DrawItem += new DrawListViewItemEventHandler(lvBase_DrawItem);
            lvBase.MouseMove += new MouseEventHandler(lvBase_MouseMove);
            lvBase.MouseLeave += new EventHandler(lvBase_MouseLeave);
            lvBase.SizeChanged += new EventHandler(lvBase_SizeChanged);
        }

        void lvBase_SizeChanged(object sender, EventArgs e)
        {
            Int32 RightOffSet = 0;
            if (Environment.OSVersion.Version >= new Version(6, 0, 0, 0))
            {
                RightOffSet = 17;
            }
            else
            {
                RightOffSet = 30;
            }

            Size tmpSize = lvBase.TileSize;
            tmpSize.Width = lvBase.Width - RightOffSet;
            if (tmpSize.Width > 0 && tmpSize.Height > 0)
            {
                lvBase.TileSize = tmpSize;
            }
        }

        void lvBase_MouseLeave(object sender, EventArgs e)
        {
            highLighItem = null;
            lvBase.Invalidate();
        }

        void lvBase_MouseMove(object sender, MouseEventArgs e)
        {
            ListViewItem item = lvBase.GetItemAt(e.X, e.Y);
            if (item == null)
            {
                if (highLighItem != null)
                {
                    lvBase.Invalidate(highLighItem.Bounds);
                }
            }
            else
            {
                if (highLighItem != null)
                {
                    if (highLighItem != item)
                    {
                        lvBase.Invalidate(highLighItem.Bounds);
                        if (!item.Selected)
                        {
                            lvBase.Invalidate(item.Bounds);
                        }
                    }
                }
                else
                {
                    if (!item.Selected)
                    {
                        lvBase.Invalidate(item.Bounds);
                    }
                }
            }
            highLighItem = item;
        }

        //画项
        void lvBase_DrawItem(object sender, DrawListViewItemEventArgs e)
        {
            Graphics g = e.Graphics;
            DrawListViewItem(e);
        }

        //画列标题
        void lvBase_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
        {
            Graphics g = e.Graphics;
            GraphicHelper.DrawRectButton(g, e.Bounds, skinEng.BackColor, 1);

            if (e.Bounds.Width != 0)
            {
                StringFormat sf = new StringFormat();
                sf.LineAlignment = StringAlignment.Center;
                sf.Alignment = StringAlignment.Center;

                string displayText = SkinHelpers.GraphicHelper.GetAppropriateString(g, e.Header.Text, e.Font, e.Bounds);
                g.DrawString(displayText, e.Font, new SolidBrush(e.ForeColor), e.Bounds, sf);
            }

            if (e.ColumnIndex == lvBase.Columns.Count - 1)
            {
                Rectangle tmpRect = e.Bounds;
                tmpRect.X += tmpRect.Width;
                tmpRect.Width = lvBase.Width;
                GraphicHelper.DrawRectButton(g, tmpRect, skinEng.BackColor, 1);
            }
        }

        //画对象
        private void DrawListViewItem(DrawListViewItemEventArgs e)
        {
            ListViewItem newLvi = e.Item;
            Graphics g = e.Graphics;

            Int32 SmallImageWidth = 0;
            Int32 SmallImageHeight = 0;
            Int32 LargeImageWidth = 0;
            Int32 LargeImageHeight = 0;
            if (lvBase.SmallImageList != null)
            {
                SmallImageWidth = lvBase.SmallImageList.ImageSize.Width;
                SmallImageHeight = lvBase.SmallImageList.ImageSize.Height;
            }
            if (lvBase.LargeImageList != null)
            {
                LargeImageWidth = lvBase.LargeImageList.ImageSize.Width;
                LargeImageHeight = lvBase.LargeImageList.ImageSize.Height;
            }

            SolidBrush newSb = new SolidBrush(lvBase.BackColor);
            g.FillRectangle(newSb, new Rectangle(newLvi.Bounds.Left, newLvi.Bounds.Top, newLvi.Bounds.Width, newLvi.Bounds.Height));

            Int32 imageLeftOffset = 0;
            Int32 imageTopOffset = 0;

            switch (lvBase.View)
            {
                case View.Tile:
                    {
                        imageLeftOffset = 2;
                        imageTopOffset = (newLvi.Bounds.Height - LargeImageHeight) / 2;
                        break;
                    }
                case View.LargeIcon:
                    {
                        imageLeftOffset = (newLvi.Bounds.Width - LargeImageWidth) / 2;
                        imageTopOffset = 2;
                        break;
                    }
                case View.SmallIcon:
                    {
                        imageLeftOffset = 0;
                        imageTopOffset = 0;
                        break;
                    }
                case View.List:
                    {
                        imageLeftOffset = 0;
                        imageTopOffset = 0;
                        break;
                    }
                case View.Details:
                    {
                        imageLeftOffset = 4;
                        imageTopOffset = 0;
                        break;
                    }
            }

            //画图片
            if (newLvi.ImageList != null)
            {
                if (newLvi.ImageIndex >= 0)
                {
                    Image itemImage = newLvi.ImageList.Images[newLvi.ImageIndex];
                    g.DrawImage(itemImage, newLvi.Bounds.Left + imageLeftOffset, newLvi.Bounds.Top + imageTopOffset);
                }
                else if (newLvi.ImageKey != String.Empty)
                {
                    if (newLvi.ImageList.Images.ContainsKey(newLvi.ImageKey))
                    {
                        Image itemImage = newLvi.ImageList.Images[newLvi.ImageKey];
                        g.DrawImage(itemImage, newLvi.Bounds.Left + imageLeftOffset, newLvi.Bounds.Top + imageTopOffset);
                    }
                }
            }

            //文字矩形列表
            List<RectangleF> SubTextRect = new List<RectangleF>(newLvi.SubItems.Count);
            List<Single> SubTextHeight = new List<float>(newLvi.SubItems.Count);
            switch (lvBase.View)
            {
                case View.Tile:
                    {
                        Int32 stringLeftOffset = 2 * imageLeftOffset + LargeImageWidth;

                        Single TotalHeight = 0;
                        for (int i = 0; i <= newLvi.SubItems.Count - 1; i++)
                        {
                            SizeF strSize = g.MeasureString(newLvi.SubItems[i].Text, newLvi.Font);
                            SubTextHeight.Add(strSize.Height + 1);
                            TotalHeight += strSize.Height + 1;
                        }

                        if (TotalHeight <= newLvi.Bounds.Height + 0)
                        {
                            Single stringTopOffset = 0;
                            stringTopOffset = (newLvi.Bounds.Height + 0 - TotalHeight) / 2;
                            Single currentTop = stringTopOffset + 0 / 2;
                            for (int i = 0; i <= newLvi.SubItems.Count - 1; i++)
                            {
                                RectangleF tmpRect = new RectangleF(newLvi.Bounds.Left + stringLeftOffset, newLvi.Bounds.Top + currentTop, newLvi.Bounds.Width - stringLeftOffset, SubTextHeight[i]);
                                SubTextRect.Add(tmpRect);
                                currentTop += SubTextHeight[i];
                            }
                        }
                        else
                        {
                            Single stringTopOffset = 1;
                            SubTextHeight[0] = (newLvi.Bounds.Height - 2) / 2;
                            SubTextRect.Add(new RectangleF(newLvi.Bounds.Left + stringLeftOffset, newLvi.Bounds.Top + stringTopOffset, newLvi.Bounds.Width - stringLeftOffset, SubTextHeight[0]));

                            Single otherItemHeight = (newLvi.Bounds.Height - SubTextHeight[0] - 2) / (newLvi.SubItems.Count - 1);
                            for (int i = 1; i <= newLvi.SubItems.Count - 1; i++)
                            {
                                SubTextHeight[i] = otherItemHeight;
                                RectangleF tmpRect = new RectangleF(newLvi.Bounds.Left + stringLeftOffset, newLvi.Bounds.Top + SubTextHeight[0] + otherItemHeight * (i - 1), newLvi.Bounds.Width - stringLeftOffset, SubTextHeight[i]);
                                SubTextRect.Add(tmpRect);
                            }
                        }
                        break;
                    }
                case View.LargeIcon:
                    {
                        RectangleF tmpRect = new RectangleF(newLvi.Bounds.Left + 1, newLvi.Bounds.Top + imageTopOffset + LargeImageHeight, newLvi.Bounds.Width - 2 * 1, newLvi.Bounds.Height - imageTopOffset - LargeImageHeight);
                        SubTextRect.Add(tmpRect);
                        break;
                    }
                case View.SmallIcon:
                case View.List:
                    {
                        RectangleF tmpRect = new RectangleF(newLvi.Bounds.Left + 2 * imageLeftOffset + SmallImageWidth, newLvi.Bounds.Top + 1, newLvi.Bounds.Width, newLvi.Bounds.Height - 2 * 1);
                        SubTextRect.Add(tmpRect);
                        break;
                    }
                case View.Details:
                    {
                        RectangleF tmpRect = new RectangleF(newLvi.Bounds.Left + imageLeftOffset + SmallImageWidth, newLvi.Bounds.Top, lvBase.Columns[0].Width - imageLeftOffset - SmallImageWidth, newLvi.Bounds.Height);
                        SubTextRect.Add(tmpRect);
                        Single currentLeft = lvBase.Columns[0].Width + e.Bounds.Left;
                        for (int i = 1; i <= newLvi.SubItems.Count - 1; i++)
                        {
                            tmpRect = new RectangleF(currentLeft + imageLeftOffset, newLvi.Bounds.Top + 1, lvBase.Columns[i].Width - imageLeftOffset, newLvi.Bounds.Height);
                            SubTextRect.Add(tmpRect);
                            currentLeft += lvBase.Columns[i].Width;
                        }
                        break;
                    }
            }

            //画文字部分
            SolidBrush strSB = new SolidBrush(newLvi.ForeColor);
            for (int i = 0; i <= newLvi.SubItems.Count - 1; i++)
            {
                ListViewItem.ListViewSubItem subItem = newLvi.SubItems[i];
                if (lvBase.View != View.Details)
                {
                    strSB.Color = subItem.ForeColor;
                }

                StringFormat strSf = new StringFormat();
                if (lvBase.View == View.LargeIcon)
                {
                    strSf.Alignment = StringAlignment.Center;
                    strSf.LineAlignment = StringAlignment.Near;
                }
                else
                {
                    strSf.Alignment = StringAlignment.Near;
                    strSf.LineAlignment = StringAlignment.Center;
                }

                string displayText = SkinHelpers.GraphicHelper.GetAppropriateString(g, subItem.Text, newLvi.Font, SubTextRect[i]);
                g.DrawString(displayText, newLvi.Font, strSB, SubTextRect[i], strSf);

                if (!(lvBase.View == View.Tile || lvBase.View == View.Details))
                {
                    break;
                }
            }
            //画高亮部分
            if (newLvi.Selected)
            {
                DrawHighLightRect(newLvi, g, ColorHelper.GetDLColor(skinEng.BackColor), true);
            }
            else if (newLvi.Equals(highLighItem))
            {
                DrawHighLightRect(newLvi);
            }
        }

        private void DrawHighLightRect(ListViewItem item)
        {
            DrawHighLightRect(item, lvBase.CreateGraphics(), skinEng.BackColor, false);
        }

        private void DrawHighLightRect(ListViewItem item, Graphics g, Color hightLightColor, Boolean IsAllColor)
        {
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

            Color topColor;
            Color baseColor = Color.FromArgb(80, hightLightColor);

            if (IsAllColor)
            {
                topColor = Color.FromArgb(30, hightLightColor);
            }
            else
            {
                topColor = Color.FromArgb(30, Color.White);
            }

            System.Drawing.Drawing2D.LinearGradientBrush sb = new System.Drawing.Drawing2D.LinearGradientBrush(item.Bounds, topColor, baseColor, System.Drawing.Drawing2D.LinearGradientMode.Vertical);
            Region rgn = GraphicHelper.CreateRoundRectRgn(item.Bounds.Left, item.Bounds.Top, item.Bounds.Right, item.Bounds.Bottom, 4, 4);
            g.FillRegion(sb, rgn);

            Pen sPen = new Pen(hightLightColor);
            g.DrawLine(sPen, item.Bounds.Left + 4 - 1, item.Bounds.Top, item.Bounds.Right - 4, item.Bounds.Top);
            g.DrawLine(sPen, item.Bounds.Left + 4 - 1, item.Bounds.Bottom - 1, item.Bounds.Right - 4, item.Bounds.Bottom - 1);

            g.DrawLine(sPen, item.Bounds.Left, item.Bounds.Top + 4 - 1, item.Bounds.Left, item.Bounds.Bottom - 4);
            g.DrawLine(sPen, item.Bounds.Right - 1, item.Bounds.Top + 4 - 1, item.Bounds.Right - 1, item.Bounds.Bottom - 4);

            g.DrawArc(sPen, new Rectangle(item.Bounds.Left, item.Bounds.Top, 4, 4), -180, 90);
            g.DrawArc(sPen, new Rectangle(item.Bounds.Right - 4 - 1, item.Bounds.Top, 4, 4), -90, 90);
            g.DrawArc(sPen, new Rectangle(item.Bounds.Right - 4 - 1, item.Bounds.Bottom - 4 - 1, 4, 4), 0, 90);
            g.DrawArc(sPen, new Rectangle(item.Bounds.Left, item.Bounds.Bottom - 4 - 1, 4, 4), 90, 90);

            sb.Dispose();
            sPen.Dispose();
        }
    }
}
